package com.feeyo.location

import android.content.Context
import com.amap.api.location.AMapLocationClient
import com.amap.api.location.AMapLocationClientOption
import com.blankj.utilcode.util.NetworkUtils
import com.feeyo.groundservice.base_util.FyLog

/**
 * 高德定位工具类
 * 网络+gps>网络>gps(室内效果差)
 */
const val LOCATION_INTERVAL = 300L//5分钟

class LocationClient(context: Context) {

    private val TAG = javaClass.simpleName
    private val location: AMapLocationClient = AMapLocationClient(context)
    private val option: AMapLocationClientOption = AMapLocationClientOption()

    init {
        //初始化定位

        //初始化定位参数
        //Battery_Saving为低功耗模式，Device_Sensors是仅设备模式
        option.locationMode = AMapLocationClientOption.AMapLocationMode.Device_Sensors
        //设置是否返回地址信息（默认返回地址信息）
        option.isNeedAddress = true
//        //设置是否只定位一次,默认为false
//        option.isOnceLocation = true
//        //给定位客户端对象设置定位参数
//        location.setLocationOption(option)
        option.locationPurpose = AMapLocationClientOption.AMapLocationPurpose.Transport
    }

    /**
     * 请求定位一次
     */
    fun requestOnce() {
        //获取一次定位结果
        option.isOnceLocation = true
        location.setLocationOption(option)
        //启动定位
        location.startLocation()
    }

    /**
     * 请求连续定位,不需要定位时，调用release
     * @param internal 间隔时间（单位：毫秒）
     */
    fun request(internal: Long = 5000) {
        option.isOnceLocation = false
        option.interval = internal
        location.setLocationOption(option)
        //启动定位
        location.startLocation()
    }

    /**设置定位回调监听**/
    fun setLocationListener(listener: LocationListener? = null) {
        //设置定位回调监听
        location.setLocationListener { amapLocation ->
            if (amapLocation != null && amapLocation.errorCode != 0) {
                //显示错误信息ErrCode是错误码，errInfo是错误信息，详见错误码表。
                FyLog.e(
                    TAG, "location Error, ErrCode:"
                            + amapLocation.errorCode + ", errInfo:"
                            + amapLocation.errorInfo + ",description:"
                            + amapLocation.description + "," + amapLocation.street
                )
                LocationException.showMsg(amapLocation.errorCode)
                //定位失败回调
                listener?.onError(amapLocation.errorCode)
            } else {
                listener?.onLocationChange(
                    amapLocation.longitude,
                    amapLocation.latitude,
                    amapLocation.country,
                    amapLocation.province,
                    amapLocation.city,
                    amapLocation.district,
                    amapLocation.street, amapLocation.speed, amapLocation.bearing
                )
            }
        }
    }

    /**设置定位参数  如果是公网可以使用这个函数重新校定，其他的如专网 默认初始化就行了，使用的是GPS的模式**/
    fun setOption() {
        var label = ""
        if (NetworkUtils.isConnected() && GPSUtil.isOpenGps()) {
            //有网络和gps开启时，高精度定位模式,会同时使用网络定位和GPS定位，优先返回最高精度的定位结果，以及对应的地址描述信息
            option.locationMode = AMapLocationClientOption.AMapLocationMode.Hight_Accuracy
            label = "GPS和网络定位"
        } else if (NetworkUtils.isConnected()) {
            //只有网络时，低功耗定位模式，不会使用GPS和其他传感器，只会使用网络定位（Wi-Fi和基站定位）
            option.locationMode = AMapLocationClientOption.AMapLocationMode.Battery_Saving
            label = "网络定位"
        } else if (GPSUtil.isOpenGps()) {
            //只有GPS时，设备定位模式，不需要连接网络，只使用GPS进行定位，这种模式下不支持室内环境的定位，需要在室外环境下才可以成功定位
            option.locationMode = AMapLocationClientOption.AMapLocationMode.Device_Sensors
            label = "GPS定位"
        }

        FyLog.e(TAG, label)
        //获取最近3s内精度最高的一次定位结果
        //option.isOnceLocationLatest = true
    }

    fun enableBackgroundLocation(open: Boolean, notifyId: Int) {
        if (open)
            location.enableBackgroundLocation(
                notifyId,
                BackgroundLocationNotify().buildNotification()
            )
        else
            location.disableBackgroundLocation(true)
    }

    /**
     * 关闭连续定位
     */
    fun release() {
        location.stopLocation()
        //location.onDestroy()
    }

    fun destroy() {
        location.onDestroy()
    }

    fun getOption() = option
}

interface LocationListener {
    fun onLocationChange(
        longitude: Double,
        latitude: Double,
        country: String,
        province: String,
        city: String,
        district: String,
        street: String,
        speed: Float = 0f,
        bearing: Float = 0f
    )

    fun onError(errorCode: Int) {}
}